package org.ghost.parallel.demo.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.locks.LockSupport;

public class LockSupportTest {
    private final Logger logger = LoggerFactory.getLogger(LockSupportTest.class);
    final Object obj = new Object();

    /**
     * wait和notify/notifyAll方法只能在同步代码块里用
     */
    public void print1() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int sum = 0;
                for (int i = 0; i < 10; i++) {
                    sum += i;
                }
                try {
                    obj.wait();
                } catch (Exception e) {
                    logger.error("*****LockSupportTest.print1出现异常,{},{}", e.getMessage(), e);
                }
                logger.info("*****LockSupportTest.print1之后sum={}", sum);
            }
        });
        thread.start();
        //休眠几秒，保证线程thread已经计算完成，阻塞在wait方法
        Thread.sleep(3000);
        obj.notify();
    }

    public void print2() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int sum = 0;
                for (int i = 0; i < 10; i++) {
                    sum += i;
                }
                try {
                    synchronized (obj) {
                        obj.wait();
                    }
                } catch (Exception e) {
                    logger.error("*****LockSupportTest.print2出现异常,{},{}", e.getMessage(), e);
                }
                logger.info("*****LockSupportTest.print2之后sum={}", sum);
            }
        });
        thread.start();
        //休眠几秒，保证线程thread已经计算完成，阻塞在wait方法
        Thread.sleep(3000);
        synchronized (obj) {
            obj.notify();
        }
    }

    /**
     * LockSupport比Object的wait/notify有两大优势
     * 1、LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了，实现了线程间的解耦。
     * 2、unpark方法可以先于park调用，所以不需要担心线程间的执行的先后顺序
     */
    public void print3() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int sum = 0;
                for (int i = 0; i < 10; i++) {
                    sum += i;
                }
                LockSupport.park();
                logger.info("*****LockSupportTest.print3之后sum={}", sum);
            }
        });
        thread.start();
        //休眠几秒，保证线程thread已经计算完成，阻塞在wait方法
        Thread.sleep(3000);
        LockSupport.unpark(thread);
    }
}
